package com.iamback.dy.task.taskjob;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.UUID;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.green.model.v20180509.ImageSyncScanRequest;
import com.aliyuncs.green.model.v20180509.TextScanRequest;
import com.aliyuncs.green.model.v20180509.VideoAsyncScanRequest;
import com.aliyuncs.green.model.v20180509.VideoAsyncScanResultsRequest;
import com.aliyuncs.http.FormatType;
import com.aliyuncs.http.HttpResponse;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
 

@Service
public class AliAuditAdapter {
	// 阿里云accessKeyId、accessKeySecret
	public final static String accessKeyId = "LTAIgMzRMMwedXmw";
	public final static String accessKeySecret = "pwtD4w0xUOIwtLFVDzM8VSTlABoqXn";
	// 调用阿里绿网服务的regionId，支持cn-shanghai
	public final static String regionId = "cn-shanghai";
	//进行留空，一次最大发三个
	private static final int FLOWCONTROL = 5;

	private TreeMap<String, String> taskid_code_Map = new TreeMap<String, String>();
	
	private Object VLOCK = new Object();
	
	private static Logger ILOG = LogManager.getLogger(AliAuditAdapter.class);
	/**
	 * HashMap<String,String>保存url和contentid的对应关系，支持批量上传进行校验检查
	 * 阿里提交有流控限制，一次只能提交若干个，而且有流控，所以单次提交，如果出现留空提醒，则把未成功的列表加入hash中，selecp1秒钟，下次再提交。
	 * @param param
	 * @throws ClientException
	 * @throws UnsupportedEncodingException
	 * @throws InterruptedException 
	 */
	public int submitVideo(String reqUrl , String reqContentId) throws ClientException, UnsupportedEncodingException, InterruptedException {

		if (reqUrl == null || "".equals(reqUrl.trim())){
			//ILOG.info("submitVideo:{}|fail url is null",reqContentId);
			return -1;
		}
		// 请替换成你自己的accessKeyId、accessKeySecret
		IClientProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);
		DefaultProfile.addEndpoint(regionId, regionId, "Green", getDomain());
		IAcsClient client = new DefaultAcsClient(profile);

		VideoAsyncScanRequest videoAsyncScanRequest = new VideoAsyncScanRequest();
		videoAsyncScanRequest.setAcceptFormat(FormatType.JSON); // 指定api返回格式
		videoAsyncScanRequest.setMethod(com.aliyuncs.http.MethodType.POST); // 指定请求方法

		List<Map<String, Object>> tasks = new ArrayList<Map<String, Object>>();
		Map<String, Object> task = null;


		task = new LinkedHashMap<String, Object>();
		task.put("dataId", UUID.randomUUID().toString());
		task.put("interval", 2);
		task.put("length", 3600);
		task.put("url", reqUrl);
		tasks.add(task);



		JSONObject data = new JSONObject();
		data.put("scenes", Arrays.asList("porn", "terrorism"));
		data.put("tasks", tasks);

		videoAsyncScanRequest.setHttpContent(data.toJSONString().getBytes("UTF-8"), "UTF-8", FormatType.JSON);

		/**
		 * 请务必设置超时时间
		 */
		videoAsyncScanRequest.setConnectTimeout(3000);
		videoAsyncScanRequest.setReadTimeout(6000);
		try {
			HttpResponse httpResponse = client.doAction(videoAsyncScanRequest);

			if (!httpResponse.isSuccess()) {
				ILOG.error("submitVideo:({})fail http response not success. status:" + httpResponse.getStatus(),reqContentId);
				return 8000 + httpResponse.getStatus();
			}
			
			JSONObject jo = JSON.parseObject(new String(httpResponse.getHttpContent(), "UTF-8"));
			String code = jo.getString("code");
			if (!"200".equals(code)) {
				if ("588".equals(code)){
					ILOG.error("submitVideo:({})fail response 558 flowcontrol selecp 1s ...,query len is:",reqContentId);
					Thread.sleep(1000);
					return this.submitVideo(reqUrl, reqContentId);
				}
				else{
				    ILOG.error("submitVideo:({"+reqContentId+"})fail response code error:" + code);
				    ILOG.error("err masg:" + jo);
				    return Integer.parseInt(code);
				}
			}
			JSONArray dataArr = jo.getJSONArray("data");
			 
			for (int i = 0; i < dataArr.size(); i++) {
				JSONObject onedata = (JSONObject) dataArr.get(i);
//				String ret_code = onedata.getString(code);
//				String ret_url = onedata.getString("url");
				String ret_taskId = onedata.getString("taskId");

				synchronized (VLOCK) {
					this.taskid_code_Map.put(ret_taskId, reqContentId);
				}
				return 0;
			}

	
		} catch (ServerException e) {
			ILOG.error("submitVideo:({})fail ServerException",reqContentId, e);
		} catch (ClientException e) {
			ILOG.error("submitVideo:({})fail ClientException",reqContentId, e);
		}
		return 600;
	}

	/**
	 * 将成员变量中的所有内容遍历并且返回 key=contentid,value=result
	 * 
	 * @return
	 * @throws ClientException
	 * @throws UnsupportedEncodingException
	 */
	public HashMap<String, Integer> getResult() throws ClientException, UnsupportedEncodingException {
		ILOG.info("begin to get auth redio result the resultMap size is:" + this.taskid_code_Map.size());
		// 请替换成你自己的accessKeyId、accessKeySecret
		IClientProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);
		DefaultProfile.addEndpoint(regionId, regionId, "Green", getDomain()); // 添加自定义endpoint。

		IAcsClient client = new DefaultAcsClient(profile);

		VideoAsyncScanResultsRequest videoAsyncScanResultsRequest = new VideoAsyncScanResultsRequest();
		videoAsyncScanResultsRequest.setAcceptFormat(FormatType.JSON); // 指定api返回格式

		JSONArray data = new JSONArray();
		int c = 0;
		synchronized (VLOCK) {
			for (String taskId : this.taskid_code_Map.keySet()) {
				if (c >= FLOWCONTROL){
					break;
				}
				data.add(taskId);
				c++;
			}
		}

		videoAsyncScanResultsRequest.setHttpContent(data.toJSONString().getBytes("UTF-8"), "UTF-8", FormatType.JSON);

		/**
		 * 请务必设置超时时间
		 */
		videoAsyncScanResultsRequest.setConnectTimeout(3000);
		videoAsyncScanResultsRequest.setReadTimeout(6000);

		HashMap<String, Integer> resultMap = new HashMap<String, Integer>();
		try {
			HttpResponse httpResponse = client.doAction(videoAsyncScanResultsRequest);
			
			if (!httpResponse.isSuccess()) {
				ILOG.error("response not success. status:" + httpResponse.getStatus());
				return null;
			}

			JSONObject jo = JSON.parseObject(new String(httpResponse.getHttpContent(), "UTF-8"));
			String code = jo.getString("code");
			if (!"200".equals(code)) {
				ILOG.error("getResult:fail response code error:" + code);
				return null;
			}
			JSONArray dataArr = jo.getJSONArray("data");
			
			//System.out.println(JSON.toJSONString(jo, true));

			for (int i = 0; i < dataArr.size(); i++) {
				JSONObject onedata = (JSONObject) dataArr.get(i);
				String ret_code = onedata.getString("code");
//				String ret_url = onedata.getString("url");
				String ret_taskId = onedata.getString("taskId");
				String contentId = this.taskid_code_Map.get(ret_taskId);
				JSONArray results = onedata.getJSONArray("results");
				if ("200".equals(ret_code)) {
					String ret = null;
					int rCode = -1;
					for (int ii = 0; ii < results.size(); ii++) {
						JSONObject result = (JSONObject) results.get(ii);
//						String scene = result.getString("result");
						String suggestion = result.getString("suggestion");
						if (ret == null || "pass".equals(ret) || "block".equals(suggestion)) {
							ret = suggestion;
						}
					}
					if ("pass".equals(ret)){
						rCode = 0;
					}
					else if ("block".equals(ret)){
						rCode = 2;
					}
					else{
						rCode =1;
					}
					// 记录一次结果
					synchronized (VLOCK) {
						resultMap.put(contentId, rCode);
						taskid_code_Map.remove(ret_taskId);
					}
				}
				else if ("280".equals(ret_code)){
					ILOG.error("getResult:{"+contentId+"}processing:" + onedata);
				}
				else {
					ILOG.error("getResult:{"+contentId+"}fail task not success. msg:" + onedata);
					resultMap.put(this.taskid_code_Map.get(ret_taskId), Integer.parseInt(ret_code));
                	taskid_code_Map.remove(ret_taskId);
				}
			}
	
		} catch (ServerException e) {
			ILOG.error("submitVideo ServerException", e);
		} catch (ClientException e) {
			ILOG.error("submitVideo ClientException", e);
		}
		return resultMap;
	}

	protected static String getDomain() {
		if ("cn-shanghai".equals(regionId)) {
			return "green.cn-shanghai.aliyuncs.com";
		}

		if ("cn-hangzhou".equals(regionId)) {
			return "green.cn-hangzhou.aliyuncs.com";
		}

		if ("local".equals(regionId)) {
			return "api.green.alibaba.com";
		}

		return "green.cn-shanghai.aliyuncs.com";
	}

	
	/**
	 * 用同步方式进行图片校验，图片也有流控，这个要注意
	 * 所以一旦发起流控，就先记录缓存，然后下一次再进行处理
	 * @param url
	 * @return -1 url 有问题
	 * @throws ClientException 
	 * @throws UnsupportedEncodingException 
	 */
	public int auditImage(String reqUrl,String reqContentId) throws ClientException, UnsupportedEncodingException{
		ILOG.info("begin ali audit image !" + reqUrl);
		if (reqUrl == null || "".equals(reqUrl.trim())){
			ILOG.info("auditImage:{}fail url is null",reqContentId);
			return -1;
		}
		
		//请替换成你自己的accessKeyId、accessKeySecret
        IClientProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);
        DefaultProfile.addEndpoint(regionId, regionId, "Green", getDomain());
        IAcsClient client = new DefaultAcsClient(profile);

        ImageSyncScanRequest imageSyncScanRequest = new ImageSyncScanRequest();
        imageSyncScanRequest.setAcceptFormat(FormatType.JSON); // 指定api返回格式
        imageSyncScanRequest.setMethod(com.aliyuncs.http.MethodType.POST); // 指定请求方法
        imageSyncScanRequest.setEncoding("utf-8");
        imageSyncScanRequest.setRegionId(regionId);


        List<Map<String, Object>> tasks = new ArrayList<Map<String, Object>>();
        
		ILOG.info("check url is :" + reqUrl);
		Map<String, Object> task = new LinkedHashMap<String, Object>();
	    task.put("dataId", UUID.randomUUID().toString());
	    task.put("url", reqUrl);
	    task.put("time", new Date());
	    
	    tasks.add(task);

    
        JSONObject data = new JSONObject();
        /**
         * porn: 色情
         * terrorism: 暴恐
         * qrcode: 二维码
         * ad: 图片广告
         * ocr: 文字识别
         */
        data.put("scenes", Arrays.asList("porn","terrorism","ad"));
        data.put("tasks", tasks);
        
        ILOG.info("img audi request json is:" + data.toJSONString());

        imageSyncScanRequest.setHttpContent(data.toJSONString().getBytes("UTF-8"), "UTF-8", FormatType.JSON);

        /**
         * 请务必设置超时时间
         */
        imageSyncScanRequest.setConnectTimeout(3000);
        imageSyncScanRequest.setReadTimeout(6000);

        try {
            HttpResponse httpResponse = client.doAction(imageSyncScanRequest);


            if (!httpResponse.isSuccess()) {
            	ILOG.error("auditImage:{}fail http response not success. status:" + httpResponse.getStatus(),reqContentId);
            	return 8000 + httpResponse.getStatus();
            }
            JSONObject scrResponse = JSON.parseObject(new String(httpResponse.getHttpContent(), "UTF-8"));

        	if (588 ==  scrResponse.getInteger("code")){
        		//如果是限流，那么sleep以后，重新调用
				ILOG.error("auditImage:{}fail  response 558 flowcontrol selecp 1s ...,query len is:",reqContentId);
				Thread.sleep(1000);
				return this.auditImage(reqUrl,reqContentId);
			}
        	if (200 != scrResponse.getInteger("code")) {
            	ILOG.error("auditImage:{}fail detect not success. code,and remove data:" + scrResponse,reqContentId);
            	return scrResponse.getInteger("code");
        	}
            //System.out.println(JSON.toJSONString(scrResponse, true));
            JSONArray taskResults = scrResponse.getJSONArray("data");
            for (Object taskResult : taskResults) {
                if(200 == ((JSONObject)taskResult).getInteger("code")){
//                	String url = ((JSONObject)taskResult).getString("url");
                    JSONArray sceneResults = ((JSONObject)taskResult).getJSONArray("results");
                    String ret = null;
                    int rcode = -1;
                    for (Object sceneResult : sceneResults) {
                        String suggestion = ((JSONObject)sceneResult).getString("suggestion");
                        //根据scene和suggetion做相关的处理
                        //do something
                        if (ret == null || "pass".equals(ret) || "block".equals(suggestion)){
                        	ret = suggestion;
                        }
                    }
                    if ("pass".equals(ret)){
                    	rcode = 0;
                    }
                    else if("block".equals(ret)){
                    	rcode = 2;
                    }
                    else {
                    	rcode = 1;
                    }

                    return rcode;
                }
                else{
                	ILOG.error("auditImage:{}fail task process fail:" + taskResult,reqContentId);
                	return ((JSONObject)taskResult).getInteger("code");
                }
            }

        } catch (ServerException e) {
            ILOG.error("auditImage:{} fail:",reqContentId ,e);
        } catch (ClientException e) {
        	ILOG.error("auditImage:{} fail:",reqContentId ,e);
        } catch (Exception e){
        	ILOG.error("auditImage:{} fail:" ,reqContentId,e);
        }
        return 600;
	}
	
//	private final static String keyword = "keyword";
	private final static String antispam = "antispam";
	
	/*
	 * 确认两个场景下，和阿里确认，只需要反垃圾的步伐
	 */
	public int auditText(String text,String contentId) throws UnsupportedEncodingException, ClientException{
		//int re1 = this.auditText(text, contentId, this.keyword);
		int re2 = this.auditText(text, contentId, antispam);
//		if (re1 > re2){
//			return re1;
//		}
//		return re2;
		return re2;
	}
	
	/**
	 * 校验文本，注意调用个顺序
	 * @param text
	 * @param contentId
	 * @return
	 * @throws ClientException 
	 * @throws UnsupportedEncodingException 
	 */
	public int auditText(String text,String contentId,String scenes) throws ClientException, UnsupportedEncodingException{
		//请替换成你自己的accessKeyId、accessKeySecret
		ILOG.info("audi text:contentid:{},text:{}", contentId, text);
        IClientProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);
        DefaultProfile.addEndpoint(regionId, regionId, "Green", getDomain());

        IAcsClient client = new DefaultAcsClient(profile);

        TextScanRequest textScanRequest = new TextScanRequest();
        textScanRequest.setAcceptFormat(FormatType.JSON); // 指定api返回格式
        textScanRequest.setMethod(com.aliyuncs.http.MethodType.POST); // 指定请求方法
        textScanRequest.setEncoding("UTF-8");
        textScanRequest.setRegionId(regionId);


        List<Map<String, Object>> tasks = new ArrayList<Map<String, Object>>();
        Map<String, Object> task1 = new LinkedHashMap<String, Object>();
        task1.put("dataId", UUID.randomUUID().toString());
        task1.put("content", text);

        tasks.add(task1);

        JSONObject data = new JSONObject();
        data.put("scenes", Arrays.asList(scenes));
        data.put("tasks", tasks);

        textScanRequest.setHttpContent(data.toJSONString().getBytes("UTF-8"), "UTF-8", FormatType.JSON);

        /**
         * 请务必设置超时时间
         */
        textScanRequest.setConnectTimeout(3000);
        textScanRequest.setReadTimeout(6000);
        try {
            HttpResponse httpResponse = client.doAction(textScanRequest);
            
            if(!httpResponse.isSuccess()){
                ILOG.error("auditText:{}fail response not success. status:" + httpResponse.getStatus(),contentId);
                return 500;
            }

       
            JSONObject scrResponse = JSON.parseObject(new String(httpResponse.getHttpContent(), "UTF-8"));

            
            if (200 != scrResponse.getInteger("code")) {
                ILOG.error("auditText:{}fail detect not success. code:{}", scrResponse.getInteger("code"),contentId);
                return 600;
            }
            

            JSONArray taskResults = scrResponse.getJSONArray("data");
            for (Object taskResult : taskResults) {
                if(200 == ((JSONObject)taskResult).getInteger("code")){
                    JSONArray sceneResults = ((JSONObject)taskResult).getJSONArray("results");
                    ILOG.info("audi text {} result is :{}",contentId,sceneResults);
                    for (Object sceneResult : sceneResults) {
                        String ret = null;
                        String suggestion = ((JSONObject)sceneResult).getString("suggestion");
                        //根据scene和suggetion做相关的处理
                        //do something
                        if (ret == null || "pass".equals(ret) || "block".equals(suggestion)){
                        	ret = suggestion;
                        }
                        int rcode = -1;
                        if ("pass".equals(ret)){
                        	rcode = 0;
                        }
                        else if("block".equals(ret)){
                        	rcode = 2;
                        }
                        else {
                        	rcode = 1;
                        }
                        return rcode;
                    }
                }else{
                	if (588 == ((JSONObject)taskResult).getInteger("code")){
                		return this.auditText(text, contentId, scenes);
                	}
                    ILOG.error("auditText:{} fail task process fail:" + taskResult,contentId);
                    return 700;
                }
            }
      
        

        } catch (ServerException e) {
        	ILOG.error("auditText:{}fail audi text error",contentId,e);
        } catch (ClientException e) {
        	ILOG.error("auditText:{}fail audi text error",contentId,e);
        } catch (Exception e){
        	ILOG.error("auditText:{}fail audi text error",contentId,e);
        }
        return 800;
	}
	
	
	
}
